<?php

namespace App\Models\Plane\Flight;

use App\Trip\Plane\Cabin\CabinClass;
use App\Trip\Plane\CarrierCode;
use Eloquent;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;

/**
 * App\Models\Plane\Flight\FlightCabin
 *
 * @property int         $id
 * @property string      $carrier_code 航班号,前2为
 * @property string      $cabin 舱位代码
 * @property int         $type 2 经济舱 1 头等舱
 * @property Carbon|null $created_at
 * @property Carbon|null $updated_at
 * @method static Builder|FlightCabin newModelQuery()
 * @method static Builder|FlightCabin newQuery()
 * @method static Builder|FlightCabin query()
 * @method static Builder|FlightCabin whereCabin($value)
 * @method static Builder|FlightCabin whereCarrierCode($value)
 * @method static Builder|FlightCabin whereCreatedAt($value)
 * @method static Builder|FlightCabin whereId($value)
 * @method static Builder|FlightCabin whereType($value)
 * @method static Builder|FlightCabin whereUpdatedAt($value)
 * @mixin Eloquent
 */
class FlightCabin extends Model
{
    use HasFactory;

    protected $table = 'flight_cabin';
    protected $fillable
                     = [
            'carrier_code',
            'cabin',
            'type',
        ];

    public function getCabin()
    {
        return $this->cabin;
    }

    public function typeDesc()
    {
        return CabinClass::Decs()[$this->type];
    }

    /**
     * @throws Exception
     */
    public function add(string $flight_no, string $cabin, int $type): ?self
    {
        if ($flight_cabin = $this->findByFlightAndCabin($flight_no, $cabin)) {
            if ($flight_cabin->getType() != $type) {
                $flight_cabin->type = $type;
                $flight_cabin->save();
            }
            return $flight_cabin;
        }
        $carrier_code = CarrierCode::getCarrierCode($flight_no);

        return $this->create([
            'carrier_code' => $carrier_code,
            'cabin'        => $cabin,
            'type'         => $type,
        ]);
    }

    /**
     * @throws Exception
     */
    public function findByFlightAndCabin(string $flight_no, string $cabin): ?self
    {
        $carrier_code   = CarrierCode::getCarrierCode($flight_no);
        $cache_key_code = "FlightCabin:{$carrier_code}:{$cabin}";
        if (Cache::has($cache_key_code)) {
            return Cache::get($cache_key_code);
        }
        $flight_cabin = $this->where([
            'carrier_code' => $carrier_code,
            'cabin'        => $cabin,
        ])->first();
        $flight_cabin && Cache::put($cache_key_code, $flight_cabin, 30 * config('trip.ttl.day'));
        return $flight_cabin;
    }

    public function getCarrierCode()
    {
        return $this->carrier_code;
    }

    public function getType()
    {
        return $this->type;
    }

    public function listByFlight(string $flight_no): Collection
    {
        $carrier_code   = CarrierCode::getCarrierCode($flight_no);
        $cache_key_code = "FlightCabin:{$carrier_code}";
        if (Cache::has($cache_key_code)) {
            return Cache::get($cache_key_code);
        }
        $list = $this->where([
            'carrier_code' => $carrier_code,
        ])->get();
        $list?->count() && Cache::put($cache_key_code, $list, config('trip.ttl.day'));
        return $list;
    }
}
